package edu.uj.petri.model;

import edu.uj.util.Observed;
import edu.uj.util.ObserverList;
import edu.uj.petri.commands.Memento;
import edu.uj.util.Observer;

/**
 * represents place in a Petri net
 * @author Piotrek
 */
public class Place extends Node implements Observed {
    private PlaceImpl impl;

    private ObserverList observerList;

    /** event code for Observed */
    public static final int TOKENS = 1371;
    /** event code for Observed */
    public static final int NAME_CHANGE = 1372;

    Place(PlaceImpl impl) {
        this.impl = impl;
        observerList = new ObserverList();
    }

    
    /**
     * adds tokens
     * @throws IllegalArgumentException if given negative number and result of
     * addition will be negative
     */
    public void addTokens(int number) {
        if (number + impl.getTokens() < 0)
            throw new IllegalArgumentException("not enough tokens");
        impl.addTokens(number);
        observerList.notifyAllSubscribers(TOKENS);
    }

    /**
     * removes given number of tokens
     * @throws IllegalArgumentException when there is too few tokens
     */
    public void deleteTokens(int number) {
        addTokens(-number);
    }

    /**
     * sets token number
     * @throws IllegalArgumentException when argument is negative
     */
    public void setTokens(int number) {
        if (number < 0)
            throw new IllegalArgumentException("token number has to be non-negative");
        impl.setTokens(number);
        observerList.notifyAllSubscribers(TOKENS);
    }

    /**
     * retuns number of tokens
     */
    public int getTokens() {
        return impl.getTokens();
    }

    public boolean isEmpty() {
        return impl.getTokens() == 0;
    }

    public void setName(String name) {
        impl.setName(name);
        observerList.notifyAllSubscribers(NAME_CHANGE);
    }

    public String getName() {
        return impl.getName();
    }

    
    /** stores internal state in a memento */
    public Memento getMemento() {
        return impl.getMemento();
    }

    /** restores internal state of object to state stored in the memento */
    public void applyMemento(Memento memento) {
        impl.applyMemento(memento);
        observerList.notifyAllSubscribers(NAME_CHANGE);
        observerList.notifyAllSubscribers(TOKENS);
    }

    public void subscribe(Observer o) {
        observerList.subscribe(o);
    }

    public void unsubscribe(Observer o) {
        observerList.unsubscribe(o);
    }
    
    private static final long serialVersionUID = 121173084322792208L;
}
